import { InboxOutlined, RightOutlined } from '@ant-design/icons';
import { App, Button, Table, Upload } from 'antd';
import classNames from 'classnames';
import { cloneDeep, isEmpty } from 'lodash-es';
import { useMemo, useState } from 'react';
import { v4 as uuid } from 'uuid';
import * as XLSX from 'xlsx';
import { YmUpload } from 'ym-design';
import OStyle from '../ExaminationItem/index.less';
import { JUDEOPTIONS } from '../JudgeExaminationItem';
import OStyle1 from './index.less';

type IErrorListItem = {
  id: string;
  exName?: string;
  errMsg: string;
};

enum EExcelExaName {
  '单选题' = 0,
  '多选题' = 1,
  '判断题' = 2,
}

const PANEKEY = -1;
const EXCELHEADERNAMES = ['类型', '题目名称', '答案', '选项', '__EMPTY'];

export interface ExaminationBatchUploadProps {
  examinationTypeName: string;
  collPanesActiveKeys?: number[];
  onSetCollPanesActiveKeys?: (activeKeys: number[]) => void;
  onSetFormValues: (examinationList: any[], type: number) => void; // type 1:覆盖，2：追加
}

const ExaminationBatchUpload: React.FC<ExaminationBatchUploadProps> = (props) => {
  const { collPanesActiveKeys, onSetCollPanesActiveKeys, examinationTypeName, onSetFormValues } = props;
  const [errorList, setErrorList] = useState<IErrorListItem[]>([]);
  const { message, modal } = App.useApp();
  const [refreshId, setRefreshId] = useState<string>();
  // const [fileList, setFileList] = useState<any[]>([]);
  //
  /**
   *@description 回显excel数据
   * @param {any[]} list
   */
  function _insertExcelDataToForm(list: any[]) {
    //@ts-ignore
    // const excelExaType = EExcelExaName[examinationTypeName];
    // console.log('--excelExaType--:', excelExaType);
    const newArr = cloneDeep(list);
    const optionsObj = newArr.shift(); // {选项: "A",__EMPTY: "B",__EMPTY_1: "C",__EMPTY_2: "D",__EMPTY_3: "E",__EMPTY_4: "F"}
    // console.log('--optionsObj--:', optionsObj);
    newArr.pop();
    const newFormValues = newArr.reduce((prev, el, index, array) => {
      // 题目
      const content = String(el['题目名称']) || undefined;
      // 答案
      let anwserItemList: string[] | string | undefined;
      if (!isEmpty(el['答案'])) {
        if (el['类型'] === 1) {
          //多选题
          // 只考虑；,，三种替换
          el['答案'] = el['答案'].replace(/；/g, ';');
          el['答案'] = el['答案'].replace(/,/g, ';');
          el['答案'] = el['答案'].replace(/，/g, ';');
          anwserItemList = el['答案'].split(';');
        } else if (el['类型'] === 0) {
          //单选题
          anwserItemList = el['答案'];
        } else if (el['类型'] === 2) {
          //选择题  0： 错，1：对
          if (el['选项'] === '对' && el['__EMPTY'] === '错') {
            el['答案'] = el['答案'].replace(/B/g, '0');
            el['答案'] = el['答案'].replace(/A/g, '1');
          } else if (el['选项'] === '错' && el['__EMPTY'] === '对') {
            el['答案'] = el['答案'].replace(/B/g, '1');
            el['答案'] = el['答案'].replace(/A/g, '0');
          }
          anwserItemList = el['答案'];
        }
      } else {
        anwserItemList = undefined;
      }
      // 选项
      let selectItemList: any[] | undefined = [];
      if (el['选项']) {
        if (el['类型'] !== 2) {
          for (const key in optionsObj) {
            if (el[key]) {
              selectItemList.push({ itemCode: optionsObj[key], itemValue: String(el[key]) });
            }
          }
        } else {
          selectItemList = JUDEOPTIONS;
        }
      } else {
        selectItemList = undefined;
      }
      prev.push({ content, selectItemList, anwserItemList });
      return prev;
    }, []);
    console.log('--excelData转换成formData--newFormValues--:', newFormValues);

    return newFormValues;
  }

  //验证excel数据
  function _validateExcelData(list: any[]): IErrorListItem[] {
    const errorList: IErrorListItem[] = [];
    if (list.length < 4 || list.length > 22) {
      errorList.push({
        id: uuid(),
        exName: '考题数量',
        errMsg: '上传考题数量在2-22之间',
      });
    }
    // 表头 列
    const excelHeaderNames = Object.getOwnPropertyNames(list[1]);
    for (let i = 0; i < EXCELHEADERNAMES.length; i++) {
      if (excelHeaderNames.indexOf(EXCELHEADERNAMES[i]) < 0) {
        errorList.push({
          id: uuid(),
          exName: '文件列',
          errMsg: `缺少【${EXCELHEADERNAMES[i]}】列`,
        });
      }
    }

    // 题目类型错误
    for (let j = 1; j < list.length - 1; j++) {
      const typeName = EExcelExaName[Number(list[j]['类型'])];
      if (isEmpty(typeName) || (typeName && typeName !== examinationTypeName)) {
        errorList.push({
          id: uuid(),
          exName: '题目类型',
          errMsg: `只能上传${examinationTypeName}`,
        });
      }
    }

    // const optionsNum = Object.getOwnPropertyNames(list[0]).length; // list[0] = {选项: "A",__EMPTY: "B",__EMPTY1: "C",__EMPTY2: "D",__EMPTY3: "E",__EMPTY4: "F",__rowNum__:1}
    const options: string[] = []; // ['A','B','C','D','E','F']
    // 选项组成数组 ,无法循环__rowNum__
    for (const key in list[0]) {
      options.push(list[0][key]);
    }

    // options.pop();

    const newArr = cloneDeep(list);
    newArr.shift();
    newArr.pop();

    newArr.forEach((el, index) => {
      //1.答案不在表头选项时
      if (!isEmpty(el['答案'])) {
        // 只考虑；,，三种替换
        el['答案'] = el['答案'].replace(/；/g, ';');
        el['答案'] = el['答案'].replace(/,/g, ';');
        el['答案'] = el['答案'].replace(/，/g, ';');
        const ansterArr = el['答案'].split(';');
        const errorAnster = ansterArr.filter((item: string) => {
          return options.indexOf(item) === -1;
        });
        if (errorAnster.length > 0) {
          errorList.push({
            id: uuid(),
            exName: el['题目名称'] || '',
            errMsg: `答案【${errorAnster.join(',')}】超出选项范围`,
          });
        }
        // 判断题，答案不是A或者B,拦截
        if (Number(el['类型']) === 2 && el['答案'] !== 'A' && el['答案'] !== 'B') {
          errorList.push({
            id: uuid(),
            exName: el['题目名称'] || '',
            errMsg: `答案【${el['答案'] || ''}】超出选项A,B范围`,
          });
        }
      } else {
        errorList.push({
          id: uuid(),
          exName: el['题目名称'] || '',
          errMsg: '答案不得为空',
        });
      }

      // 判断题，选项限制
      if (Number(el['类型']) === 2) {
        // 判断题，选项同为对。 或者同为错拦截    两个选项分别 不是对，也不是错，拦截
        if ((el['选项'] === '对' && el['__EMPTY'] === '对') || (el['选项'] === '错' && el['__EMPTY'] === '错')) {
          errorList.push({
            id: uuid(),
            exName: el['题目名称'] || '',
            errMsg: `选项【${el['选项'] || ''}】不得相同`,
          });
        }
        if ((el['选项'] !== '对' && el['选项'] !== '错') || (el['__EMPTY'] !== '对' && el['__EMPTY'] !== '错')) {
          errorList.push({
            id: uuid(),
            exName: el['题目名称'] || '',
            errMsg: `选项【${el['选项'] || ''}】超出对，错范围`,
          });
        }
      }
      // 考题列数 超过 表头 列数
      // console.log('--options--:', options);
      // console.log('--Object.getOwnPropertyNames(el)--:', Object.getOwnPropertyNames(el));
      //Object.getOwnPropertyNames(el)不包含__rowNum__   {...,__rowNum__:1}}
      if (el['类型'] !== 2 && Object.getOwnPropertyNames(el).length > options.length + 3) {
        errorList.push({
          id: uuid(),
          exName: el['题目名称'] || '',
          errMsg: '考题列数超过表头列数',
        });
      }
      if (el['类型'] === 2 && Object.getOwnPropertyNames(el).length > 5) {
        errorList.push({
          id: uuid(),
          exName: el['题目名称'] || '',
          errMsg: '考题列数超过表头列数',
        });
      }
      //选项 AB的必须有，其他的有的话，前面必须有
      if (
        !el['选项'] ||
        !el['__EMPTY'] ||
        (el['__EMPTY_2'] && !el['__EMPTY_1']) ||
        (el['__EMPTY_3'] && (!el['__EMPTY_2'] || !el['__EMPTY_1'])) ||
        (el['__EMPTY_4'] && (!el['__EMPTY_3'] || !el['__EMPTY_2'] || !el['__EMPTY_1'])) ||
        (el['__EMPTY_5'] && (!el['__EMPTY_4'] || !el['__EMPTY_3'] || !el['__EMPTY_2'] || !el['__EMPTY_1'])) ||
        (el['__EMPTY_6'] &&
          (!el['__EMPTY_5'] || !el['__EMPTY_4'] || !el['__EMPTY_3'] || !el['__EMPTY_2'] || !el['__EMPTY_1']))
      ) {
        errorList.push({
          id: uuid(),
          exName: el['题目名称'] || '',
          errMsg: '选项列填写错误',
        });
      }

      // 单选添加页，excel有非单选提醒，选项数量大于1则报错，其他题型一样
      if (Number(el['类型']) === 0 && !isEmpty(el['答案']) && el['答案'].length > 1) {
        errorList.push({
          id: uuid(),
          exName: el['题目名称'] || '',
          errMsg: '单选题只能有一个答案',
        });
      }
      if (Number(el['类型']) === 1 && !isEmpty(el['答案']) && el['答案'].length < 2) {
        errorList.push({
          id: uuid(),
          exName: el['题目名称'] || '',
          errMsg: '多选题不能只有一个答案',
        });
      }
      if (Number(el['类型']) === 2 && el['答案'] !== 'A' && el['答案'] !== 'B') {
        errorList.push({
          id: uuid(),
          exName: el['题目名称'] || '',
          errMsg: '判断题答案只能为对或错',
        });
      }
    });

    return errorList;
  }
  // 解析excel
  const onImportExcel = (file: File) => {
    const fileReader = new FileReader();
    fileReader.readAsBinaryString(file); //二进制
    fileReader.onload = (event) => {
      // const { result } = event.target;
      const result = fileReader.result;
      let data: any[] = []; // 存储获取到的数据
      try {
        const workbook = XLSX.read(result, { type: 'binary' });
        // 遍历每张工作表进行读取（这里默认只读取第一张表）

        for (const sheet in workbook.Sheets) {
          // eslint-disable-next-line no-prototype-builtins
          if (workbook.Sheets.hasOwnProperty(sheet)) {
            // 利用 sheet_to_json 方法将 excel 转成 json 数据

            data = data.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]));

            // break; // 如果只取第一张表，就取消注释这行
          }
        }
        console.log('--解析出的excel表--：', data);
        const errorRes = _validateExcelData(data);
        console.log('--验证结果--errorRes--:', errorRes);
        setErrorList(errorRes);
        if (!isEmpty(errorRes)) {
          return Upload.LIST_IGNORE;
        } else {
          modal.confirm({
            title: '成功识别' + (data.length - 2) + '个考题，请选择导入选项',
            centered: true,
            cancelText: '覆盖',
            okText: '追加',
            onOk: () => {
              const formValues = _insertExcelDataToForm(data);
              onSetFormValues(formValues, 2);
            },
            onCancel: () => {
              const formValues = _insertExcelDataToForm(data);
              onSetFormValues(formValues, 1);
            },
          });
        }
      } catch (err) {
        message.error('文件错误');
        return Upload.LIST_IGNORE;
      }
    };

    return Upload.LIST_IGNORE;
  };

  //collapse
  const onCollPane = (e: React.MouseEvent) => {
    e.stopPropagation();
    const currIndex = collPanesActiveKeys?.findIndex((val) => val === PANEKEY);
    if (typeof currIndex === 'number' && currIndex > -1) {
      collPanesActiveKeys?.splice(currIndex, 1);
    } else {
      collPanesActiveKeys?.push(PANEKEY);
    }
    onSetCollPanesActiveKeys?.([...(collPanesActiveKeys || [])]);
  };

  const columns = useMemo(
    () => [
      {
        title: '错误位置/题目',
        key: 'exName',
        dataIndex: 'exName',
        width: 500,
        ellipsis: true,
      },
      {
        title: '错误提示',
        key: 'errMsg',
        dataIndex: 'errMsg',
        width: 250,
        ellipsis: true,
      },
    ],
    [],
  );

  //BUG: YmUpload input.value 没有置空，导致文件内容修改后上传同一个文件，无法识别文件修改
  // 方案1 value受控 ，没起作用
  // 方案2  给组件设置key 通过更新key，更新Fibre强制刷新组件
  return (
    <div className={OStyle.pane_item}>
      <div className={OStyle.item_header}>
        <div
          className={OStyle.header_text}
          onClick={(e) => {
            onCollPane(e);
          }}
        >
          <RightOutlined
            className={classNames(OStyle.text_collapse, {
              [`${OStyle.collapse_rotate}`]: collPanesActiveKeys?.includes(PANEKEY),
            })}
          />
          <span className={OStyle.text_text}>批量导入考题 </span>
        </div>
      </div>
      <div
        className={classNames(OStyle.item_content, {
          [`${OStyle1.content_upload}`]: true,
          [`${OStyle.content_hidden}`]: !collPanesActiveKeys?.includes(PANEKEY),
        })}
      >
        <YmUpload
          key={refreshId}
          maxCount={1}
          multiple={false}
          accept=".xlsx"
          acceptExt="xlsx"
          type="drag"
          listType="info-list"
          showUploadList={false}
          // beforeUpload={}
          customRequest={({ file, onSuccess }) => {
            onImportExcel(file as File);
            setRefreshId(uuid());
            // setFileList([]);
            onSuccess?.(null);
          }}
          // value={fileList}
          // onChange={(fileList) => {
          //   console.log('--onChange--fileList--：', fileList);
          //   setFileList([...fileList]);
          // }}
          style={{ width: '750px', height: '300px', margin: '24px 0 45px 0' }}
        >
          <div className={OStyle1.ym_upload_child}>
            <p className="ant-upload-drag-icon">
              <InboxOutlined />
            </p>
            <p className={OStyle1.ym_upload_text}>可将 Excel 文件拖拽此区域</p>
            <p className={OStyle1.ym_upload_btn}>
              <Button
                size="middle"
                type="primary"
                shape="round"
                style={{ paddingInlineStart: '33px', paddingInlineEnd: '33px' }}
              >
                点击上传
              </Button>
            </p>
            <p>
              <Button
                size="middle"
                type="default"
                shape="round"
                onClick={(e: React.MouseEvent) => {
                  e.stopPropagation();
                  e.preventDefault();
                  window.location.href =
                    'https://mp.logibeat.com/%E5%AF%BC%E5%85%A5%E9%A2%98%E7%9B%AE%E6%A8%A1%E6%9D%BF.xlsx';
                }}
              >
                下载Excel模板
              </Button>
            </p>
          </div>
        </YmUpload>

        {!isEmpty(errorList) && (
          <div style={{ width: '750px', height: '300px' }}>
            <span className={OStyle.error_warnning}>excel表格错误数据提示:</span>
            <Table columns={columns} dataSource={errorList} rowKey="id" size="small" pagination={false} bordered />
          </div>
        )}
      </div>
    </div>
  );
};

export default ExaminationBatchUpload;
